package earogya.ehr.medical_records;

import java.util.Iterator;
import java.util.List;
import java.util.logging.Logger;

import javax.print.attribute.standard.QueuedJobCount;
import javax.swing.text.TabExpander;

import org.hibernate.HibernateException;
import org.hibernate.Query;
import org.hibernate.QueryException;
import org.hibernate.SQLQuery;
import org.hibernate.Session;

import earogya.util.MedicalRecordsHibernateUtil;

public class HibernateManager {
	/**
	 * Save an object to database using hibernate
	 * @param obj
	 * @return
	 */
	
	
	public HibernateManager(){
		
	}
	
	public Boolean saveObject(Object obj) throws HibernateException{
		Boolean isSuccessful=true;
		Session session = MedicalRecordsHibernateUtil.getSessionFactory().getCurrentSession();
		try{
			session.beginTransaction();
			session.save(obj);
			session.getTransaction().commit();
		}catch(HibernateException e){
			isSuccessful=false;
			throw e;
		}
		return isSuccessful;
	}
	
	/**
	 * Query results from database based on the fields and values
	 * @param fieldsAndValues - names of the columns and their respective values
	 * @param required_field - name of the required column
	 * @param table - name of the table
	 * @return
	 */
	public int queryValuesFromDatabase(Object[][] fieldsAndValues, String required_field, String className, String objectName){
		int value=-1;
		Session session = MedicalRecordsHibernateUtil.getSessionFactory().getCurrentSession();
		try{
			session.beginTransaction();
			Query query=session.createQuery(this.buildSelectQuery(fieldsAndValues, required_field, className, objectName));
	        query.setMaxResults(1);
	        List list=query.list();
	        if(list.size()==1){
	        	value=(Integer)list.get(0);
	        }
		}catch(HibernateException e){
			
		}finally{
			session.close();
		}
		return value;
	}
	
	public String queryValuesFromDatabaseString(Object[][] fieldsAndValues, String required_field, String className, String objectName){
		String value=null;
		Session session = MedicalRecordsHibernateUtil.getSessionFactory().getCurrentSession();
		try{
			session.beginTransaction();
			Query query=session.createQuery(this.buildSelectQuery(fieldsAndValues, required_field, className, objectName));
	        query.setMaxResults(1);
	        List list=query.list();
	        if(list.size()==1){
	        	value=(String)list.get(0);
	        }
		}catch(HibernateException e){
			
		}finally{
			session.close();
		}
		return value;
	}
	
	public List queryValueListFromDatabase(Object[][] fieldsAndValues, String required_field, String className, String objectName){
		Session session = MedicalRecordsHibernateUtil.getSessionFactory().getCurrentSession();
		List list=null;
		try{
			session.beginTransaction();
			Query query=session.createQuery(this.buildSelectQuery(fieldsAndValues, required_field, className, objectName));
	        list=query.list();
	        String ldfs=(String)list.get(0);
		}catch(HibernateException e){
			
		}catch(Exception e){
			System.out.println(e.getStackTrace());
		}finally{
			session.close();
		}
		return list;
	}
	
	public List queryValueListFromDatabase(Object[][] fieldsAndValues, String[] required_field, String className, String objectName){
		Session session = MedicalRecordsHibernateUtil.getSessionFactory().getCurrentSession();
		List list=null;
		/*try{*/
			session.beginTransaction();
			Query query=session.createQuery(this.buildSelectQuery(fieldsAndValues, required_field, className, objectName));
	        list=query.list();
		/*}catch(HibernateException e){
			
		}catch(Exception e){
			System.out.println(e.getStackTrace());
		}finally{
			session.close();
		}*/
		return list;
	}
	
	/**
	 * Creates an sql query using the given information.
	 * @param fieldsAndValues - name of the columns and their respective values
	 * @param required_field - name of the required column 
	 * @param table - name of the table
	 * @return
	 */
	private String buildSelectQuery(Object[][] fieldsAndValues, String[] required_field, String className, String objectName){
		StringBuilder builder=new StringBuilder();
		builder.append("SELECT ");
		for(int i=0; i<required_field.length; i++){
			if(i<required_field.length-1){
				builder.append(objectName+"."+required_field[i]+", ");
			}
			else{
				builder.append(objectName+"."+required_field[i]+" FROM "+className+" AS "+objectName+" WHERE ");
			}
		}
		for(int i=0; i<fieldsAndValues.length; i++){
			if(i<fieldsAndValues.length-1){
				builder.append(objectName+"."+fieldsAndValues[i][0]+"='"+fieldsAndValues[i][1]+"' AND ");
			}else{
				builder.append(objectName+"."+fieldsAndValues[i][0]+"='"+fieldsAndValues[i][1]+"'");
			}
		}
		return builder.toString();
	}
	
	/**
	 * Creates an sql query using the given information.
	 * @param fieldsAndValues - name of the columns and their respective values
	 * @param required_field - name of the required column 
	 * @param table - name of the table
	 * @return
	 */
	private String buildSelectQuery(Object[][] fieldsAndValues, String required_field, String className, String objectName){
		StringBuilder builder=new StringBuilder();
		builder.append("SELECT "+objectName+"."+required_field+" FROM "+className+" AS "+objectName+" WHERE ");
		for(int i=0; i<fieldsAndValues.length; i++){
			if(i<fieldsAndValues.length-1){
				builder.append(objectName+"."+fieldsAndValues[i][0]+"='"+fieldsAndValues[i][1]+"' AND ");
			}else{
				builder.append(objectName+"."+fieldsAndValues[i][0]+"='"+fieldsAndValues[i][1]+"'");
			}
		}
		return builder.toString();
	}
	
	private String buildDeleteQuery(Object[][] fieldsAndValues, String className, String objectName){
		StringBuilder builder=new StringBuilder();
		builder.append("DELETE FROM "+className+" "+objectName+" WHERE ");
		for(int i=0; i<fieldsAndValues.length; i++){
			if(i<fieldsAndValues.length-1){
				builder.append(objectName+"."+fieldsAndValues[i][0]+"='"+fieldsAndValues[i][1]+"' AND ");
			}else{
				builder.append(objectName+"."+fieldsAndValues[i][0]+"='"+fieldsAndValues[i][1]+"'");
			}
		}
		return builder.toString();
	}
	
	public Boolean deleteEntry(Object[][] fieldsAndValues, String className, String objectName){
		Boolean isSuccesful=false;
		Session session = MedicalRecordsHibernateUtil.getSessionFactory().getCurrentSession();
		try{
			session.beginTransaction();
			Query query=session.createQuery(this.buildDeleteQuery(fieldsAndValues, className, objectName));
			int no_of_rows=query.executeUpdate();
			if(no_of_rows>0){
				isSuccesful=true;
			}
		}catch(HibernateException e){
			isSuccesful=false;
			throw e;
		}finally{
			session.close();
		}
		return isSuccesful;
	}
	
	public Boolean updateBhtEntry(int bht_id, int bed, int ward)throws HibernateException {
		Boolean isSuccesful=false;
		Session session = MedicalRecordsHibernateUtil.getSessionFactory().getCurrentSession();
		try{
			session.beginTransaction();
			Bht bht=(Bht)session.get(Bht.class,bht_id);
			bht.setCurrent_bed(bed);
			bht.setCurrent_ward(ward);
			session.save(bht);
			session.getTransaction().commit();
			isSuccesful=true;
		}catch(HibernateException e){
			isSuccesful=false;
			throw e;
		}
		return isSuccesful;
	}
	
	public Boolean updateAdmissionToDischargeorTransfer(int admission_id, String status)throws HibernateException {
		Boolean isSuccesful=false;
		Session session = MedicalRecordsHibernateUtil.getSessionFactory().getCurrentSession();
		try{
			session.beginTransaction();
			Admission admission=(Admission)session.get(Admission.class,admission_id);
			admission.setStatus(status);
			session.save(admission);
			session.getTransaction().commit();
			isSuccesful=true;
		}catch(HibernateException e){
			isSuccesful=false;
			throw e;
		}
		return isSuccesful;
	}
	
	
	private String buildGetMaxValueQuery(Object[][] fieldsAndValues, String required_field, String className, String objectName){
		StringBuilder builder=new StringBuilder();
		builder.append("SELECT max("+objectName+"."+required_field+") FROM "+className+" AS "+objectName+" WHERE ");
		for(int i=0; i<fieldsAndValues.length; i++){
			if(i<fieldsAndValues.length-1){
				builder.append(objectName+"."+fieldsAndValues[i][0]+"='"+fieldsAndValues[i][1]+"' AND ");
			}else{
				builder.append(objectName+"."+fieldsAndValues[i][0]+"='"+fieldsAndValues[i][1]+"'");
			}
		}
		return builder.toString();
	}
	
	private String buildGetCountQuery(Object[][] fieldsAndValues, String required_field, String className, String objectName){
		StringBuilder builder=new StringBuilder();
		builder.append("SELECT count("+objectName+"."+required_field+") FROM "+className+" AS "+objectName+" WHERE ");
		for(int i=0; i<fieldsAndValues.length; i++){
			if(i<fieldsAndValues.length-1){
				builder.append(objectName+"."+fieldsAndValues[i][0]+"='"+fieldsAndValues[i][1]+"' AND ");
			}else{
				builder.append(objectName+"."+fieldsAndValues[i][0]+"='"+fieldsAndValues[i][1]+"'");
			}
		}
		return builder.toString();
	}
	
	public int getMaxValue(Object[][] fieldsAndValues, String required_field, String className, String objectName){
		int value=-1;
		Session session = MedicalRecordsHibernateUtil.getSessionFactory().getCurrentSession();
		try{
		session.beginTransaction();
			Query query=session.createQuery(this.buildGetMaxValueQuery(fieldsAndValues, required_field, className, objectName));
	        query.setMaxResults(1);
	        List list=query.list();
	        if(list.size()==1){
	        	value=(Integer)list.get(0);
	        }
		}catch(HibernateException e){
			throw e;
		}finally{
			session.close();
		}
		return value;
	}
	
	public long getCount(Object[][] fieldsAndValues, String required_field, String className, String objectName){
		long value=-1;
		Session session = MedicalRecordsHibernateUtil.getSessionFactory().getCurrentSession();
		try{
		session.beginTransaction();
			Query query=session.createQuery(this.buildGetCountQuery(fieldsAndValues, required_field, className, objectName));
	        List list=query.list();
	        if(list.size()==1){
	        	value=(Long)list.get(0);
	        }
		}catch(HibernateException e){
			throw e;
		}finally{
			session.close();
		}
		return value;
	}
	
	public Boolean updateConsultant(int bht_id, String new_consultant_id) throws HibernateException{
		Boolean isSuccesful=false;
		Session session = MedicalRecordsHibernateUtil.getSessionFactory().getCurrentSession();
		try{
			session.beginTransaction();
			Bht bht=(Bht)session.get(Bht.class,bht_id);
			bht.setConsultant_id(new_consultant_id);
			session.save(bht);
			session.getTransaction().commit();
			isSuccesful=true;
		}catch(HibernateException e){
			isSuccesful=false;
			throw e;
		}
		return isSuccesful;
	}
	
	public String getRelationship(int relationship_id){
		String relationship=null;
		Object[][] fieldsAndValues={{"guardian_relationship_id", relationship_id}};
		String queryString=this.buildSelectQuery(fieldsAndValues, "guardian_relationship", "GuardianRelationship", "guardian_relationship");
		Session session = MedicalRecordsHibernateUtil.getSessionFactory().getCurrentSession();
		try{
			session.beginTransaction();
			Query query=session.createQuery(queryString);
			List list=query.list();
		     if(list.size()==1){
		      	relationship=(String)list.get(0);
		     }
		}catch(HibernateException e){
			throw e;
		}finally{
			session.close();
		}
		return relationship;
	}
	
	public List queryUsingJoin(String[][] classAndObjectNames, Object[][][] fieldsAndValues, String[] requiredClassAndField, String[][] joinObjectAndField){
		Session session = MedicalRecordsHibernateUtil.getSessionFactory().getCurrentSession();
		List list=null;
		try{
			session.beginTransaction();
			Query query=session.createQuery(this.buildJoinQuery(classAndObjectNames, fieldsAndValues, requiredClassAndField, joinObjectAndField));
			list=query.list();
		}catch(QueryException e){
			throw e;
		}catch(HibernateException e){
			throw e;
		}finally{
			session.close();
		}
		return list;
	}
	
	private String buildJoinQuery(String[][] classAndObjectNames, Object[][][] fieldsAndValues, String[] requiredObjectAndField, String[][] joinObjectAndField){
		StringBuilder builder=new StringBuilder();
		builder.append("select "+requiredObjectAndField[0]+"."+requiredObjectAndField[1]);
		builder.append(" from ");
		for(int i=0; i<2; i++){
			if(i<classAndObjectNames.length-1){
				builder.append(classAndObjectNames[i][0]+" as "+classAndObjectNames[i][1]+", ");
			}
			else{
				builder.append(classAndObjectNames[i][0]+" as "+classAndObjectNames[i][1]);
			}
		}
		
		builder.append(" where ");
		builder.append(" "+joinObjectAndField[0][0]+"."+joinObjectAndField[0][1]+"="+joinObjectAndField[1][0]+"."+joinObjectAndField[1][1]);
		if(fieldsAndValues.length>0){
			builder.append(" and ");
			for(int i=0; i<fieldsAndValues.length; i++){
				for(int j=0; j<fieldsAndValues[i].length; j++){
					if(j<fieldsAndValues[i].length-1|i==0){
						builder.append(classAndObjectNames[i][1]+"."+fieldsAndValues[i][j][0]+"= '"+fieldsAndValues[i][j][1]+"' and ");
					}else{
						builder.append(classAndObjectNames[i][1]+"."+fieldsAndValues[i][j][0]+"= '"+fieldsAndValues[i][j][1]+"'");
					}
				}
			}
		}
		return builder.toString();
	}
	
	public Boolean updateGuardianAddressDetails(GuardianAddressDetails g){
		Boolean isSuccesful=false;
		Session session = MedicalRecordsHibernateUtil.getSessionFactory().getCurrentSession();
		try{
			session.beginTransaction();
			GuardianAddressDetails guardian_address=(GuardianAddressDetails)session.get(GuardianAddressDetails.class,g.getGuardian_address_details_id());
			guardian_address.setCity_1(g.getCity_1());
			guardian_address.setCity_2(g.getCity_2());
			guardian_address.setCountry(g.getCountry());
			guardian_address.setHouse_number(g.getHouse_number());
			guardian_address.setStreet_name(g.getStreet_name());
			session.save(guardian_address);
			session.getTransaction().commit();
			isSuccesful=true;
		}catch(HibernateException e){
			isSuccesful=false;
			throw e;
		}
		return isSuccesful;
	}

	public Boolean updateGuardianTelephoneNumberDetails(GuardianTelephoneNumberDetails gtnd){
		Boolean isSuccesful=false;
		Session session = MedicalRecordsHibernateUtil.getSessionFactory().getCurrentSession();
		try{
			session.beginTransaction();
			int id=gtnd.getTelephone_number_details_id();
			GuardianTelephoneNumberDetails guardian_telephone_numbers=(GuardianTelephoneNumberDetails)session.get(GuardianTelephoneNumberDetails.class , id);
			guardian_telephone_numbers.setTelephone_number(gtnd.getTelephone_number());
			session.save(guardian_telephone_numbers);
			session.getTransaction().commit();
			isSuccesful=true;
		}catch(HibernateException e){
			isSuccesful=false;
			throw e;
		}
		return isSuccesful;
	}
	
	public Boolean updateEmailAddressDetails(GuardianEmailAddressDetails gead){
		Boolean isSuccesful=false;
		Session session = MedicalRecordsHibernateUtil.getSessionFactory().getCurrentSession();
		try{
			session.beginTransaction();
			GuardianEmailAddressDetails email_addresses=(GuardianEmailAddressDetails)session.get(GuardianEmailAddressDetails.class,gead.getGuardian_email_address_detials_id());
			email_addresses.setEmail_address(gead.getEmail_address());
			session.save(email_addresses);
			session.getTransaction().commit();
			isSuccesful=true;
		}catch(HibernateException e){
			isSuccesful=false;
			throw e;
		}
		return isSuccesful;
	}

	public Boolean updatePatientIdInAdmission(int new_patient_id, int admision_id)throws HibernateException {
		Boolean isSuccesful=false;
		Session session = MedicalRecordsHibernateUtil.getSessionFactory().getCurrentSession();
		try{
			session.beginTransaction();
			Admission admission=(Admission)session.get(Admission.class, admision_id);
			admission.setPatient_id(new_patient_id);
			session.save(admission);
			session.getTransaction().commit();
			isSuccesful=true;
		}catch(HibernateException e){
			isSuccesful=false;
			throw e;
		}
		return isSuccesful;
	}
}
